package com.chatplus.application.common.util;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 拼音工具类
 *
 * @author Administrator
 */
public class PinYin4JUtil {

    public static final PinyinComparator pinyinComparator = new PinyinComparator();
    private static final List<String> PINYIN_LIST = List.of("yi", "er", "san", "shan", "si", "shi", "wu", "liu", "lu", "qi", "ba", "jiu", "yao", "ling", "lin");

    public static int compare(String o1, String o2) {
        return pinyinComparator.compare(o1, o2);
    }

    static class PinyinComparator implements Comparator<String> {
        @Override
        public int compare(String o1, String o2) {
            for (int i = 0; i < o1.length() && i < o2.length(); i++) {
                int codePoint1 = o1.charAt(i);
                int codePoint2 = o2.charAt(i);

                boolean flag = Character.isSupplementaryCodePoint(codePoint1) || Character.isSupplementaryCodePoint(codePoint2);
                if (flag) {
                    i++;
                }

                if (codePoint1 != codePoint2) {
                    if (flag) {
                        return codePoint1 - codePoint2;
                    }

                    String pinyin1 = pinyin((char) codePoint1, o1);
                    String pinyin2 = pinyin((char) codePoint2, o2);

                    if (pinyin1 != null && pinyin2 != null) { // 两个字符都是汉字
                        if (!pinyin1.equals(pinyin2)) {
                            return pinyin1.compareTo(pinyin2);
                        }
                    } else {
                        return codePoint1 - codePoint2;
                    }
                }
            }
            return o1.length() - o2.length();
        }

        /**
         * 字符的拼音，多音字就得到第一个拼音。不是汉字，就return null。
         *
         * @param c
         * @param obj
         */
        private String pinyin(char c, String obj) {
            String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c);
            if (pinyinArray == null) {
                return null;
            }
            return checkSpecial(pinyinArray, obj);
        }

    }

    /**
     * 检查特别词组的情况（待进一步整理优化多音字表）
     *
     * @param pinyinArray 汉字的拼音列表（eg:[zhong4,chong2]）
     * @param obj         汉字字符串（eg:“重”）
     * @return
     */
    public static String checkSpecial(String[] pinyinArray, String obj) {
        if (Objects.nonNull(obj) && obj.startsWith("重庆")) {
            for (String pinyin : pinyinArray) {
                if (pinyin.startsWith("c")) {
                    return pinyin;
                }
            }
        }
        return pinyinArray[0];
    }

    /**
     * 省份根据拼音首字母分类
     *
     * @param provinceList 省份列表
     * @return res
     */
    public static Map<String, List<String>> groupProvinceOfInitials(List<String> provinceList) {
        Map<String, List<String>> group = new HashMap<>();
        if (CollUtil.isEmpty(provinceList)) {
            return group;
        }
        for (String province : provinceList) {
            //A-G 首字母匹配省份
            if (matcherProvince("^[澳安北重福甘广贵]", province)) {
                if (group.containsKey("A-G")) {
                    group.get("A-G").add(province);
                } else {
                    group.put("A-G", Lists.newArrayList(province));
                }
            }
            //H-K 首字母匹配省份
            if (matcherProvince("^[海河黑湖江吉]", province)) {
                if (group.containsKey("H-K")) {
                    group.get("H-K").add(province);
                } else {
                    group.put("H-K", Lists.newArrayList(province));
                }
            }
            //L-S 首字母匹配省份
            if (matcherProvince("^[辽内宁青山上山陕四]", province)) {
                if (group.containsKey("L-S")) {
                    group.get("L-S").add(province);
                } else {
                    group.put("L-S", Lists.newArrayList(province));
                }
            }
            //T-Z 首字母匹配省份
            if (matcherProvince("^[天新香西云浙]", province)) {
                if (group.containsKey("T-Z")) {
                    group.get("T-Z").add(province);
                } else {
                    group.put("T-Z", Lists.newArrayList(province));
                }
            }
        }
        return group;
    }

    public static boolean matcherProvince(String pattern, String province) {
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(province);
        return m.find();
    }

    /**
     * 给连续数字或者连续数字同音字打*
     * <p>
     * indexSize：连续数字的定义
     *
     * @param input
     * @return
     */
    public static String convertToPinyinAndReplaceWithStar(String input) {
        if (StrUtil.isBlank(input)) {
            return "";
        }
        try {
            int indexSize = 9;
            int index = 0;
            List<Integer> indexList = Lists.newArrayList();
            // 先进行拼音检测
            HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
            defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
            defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
            StringBuilder stringBuilder = new StringBuilder(input);
            for (char c : input.toCharArray()) {
                if (Character.isDigit(c)) {
                    indexList.add(index);
                } else {
                    String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c, defaultFormat);
                    if (pinyinArray != null && pinyinArray.length > 0) {
                        if (Arrays.stream(pinyinArray).anyMatch(PINYIN_LIST::contains)) {
                            indexList.add(index);
                        } else {
                            indexList.clear();
                        }
                    } else {
                        if (indexList.size() >= indexSize) {
                            stringFilterBuild(stringBuilder, indexList);
                        }
                        indexList.clear();
                    }
                }
                index++;
            }
            if (indexList.size() >= indexSize) {
                stringFilterBuild(stringBuilder, indexList);
            }
            String string = stringBuilder.toString();
            String mobileReg = "\\d{2,5}-\\d{7,8}|\\d{7,8}";
            Pattern mobilePattern = Pattern.compile(mobileReg);
            Matcher mobileMatcher = mobilePattern.matcher(string);
            string = mobileMatcher.replaceAll("*******");
            return string;
        } catch (Exception e) {
            return input;
        }
    }

    private static void stringFilterBuild(StringBuilder stringBuilder, List<Integer> indexList) {
        for (int i : indexList) {
            stringBuilder.setCharAt(i, '*');
        }
    }
}
